package com.cauli.netdisk.module.user.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cauli.netdisk.base.exception.MyException;
import com.cauli.netdisk.module.menu.service.MenuService;
import com.cauli.netdisk.module.role.model.dto.RoleDTO;
import com.cauli.netdisk.module.role.service.RoleService;
import com.cauli.netdisk.module.menu.model.dto.MenuDTO;
import com.cauli.netdisk.module.user.model.dto.UserAddDTO;
import com.cauli.netdisk.module.user.model.dto.UserDTO;
import com.cauli.netdisk.module.user.model.dto.UserDetailDTO;
import com.cauli.netdisk.module.user.model.dto.UserQueryDTO;
import com.cauli.netdisk.module.user.model.dto.UserUpdateDTO;
import com.cauli.netdisk.module.user.model.dto.UserUpdatePwdDTO;
import com.cauli.netdisk.module.user.model.dto.UserUpdateStatusDTO;
import com.cauli.netdisk.module.user.model.entity.User;
import com.cauli.netdisk.module.user.service.UserService;
import com.cauli.netdisk.module.user.mapper.UserMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Cauli
 * @date 2022-12-13 15:12:32
 * @description 用户表 服务实现类
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private RoleService roleService;

    @Autowired
    private MenuService menuService;

    @Override
    public Page<User> getUserPage(UserQueryDTO userQueryDTO) {
        return baseMapper.selectPage(userQueryDTO.toPage(), userQueryDTO.toLambdaQueryWrapper());
    }

    @Override
    public UserDetailDTO getUserDetail(Long userId) {
        UserDetailDTO userDetailDTO = new UserDetailDTO();
        // 根据用户ID获取用户信息
        User user = baseMapper.selectById(userId);
        if (user != null) {
            UserDTO userDTO = new UserDTO();
            BeanUtils.copyProperties(user, userDTO);
            userDetailDTO.setUserDTO(userDTO);

            // 根据用户ID获取角色信息
            RoleDTO roleDTO = roleService.getRoleById(userDTO.getRoleId());
            userDetailDTO.setRoleDTO(roleDTO);

            // 根据用户ID获得权限信息
            List<MenuDTO> menuDTOList = menuService.getPermissionList(userId, null);
            List<String> permissionList = menuDTOList.stream().map(MenuDTO::getPermission).collect(Collectors.toList());
            userDetailDTO.setPermissions(permissionList);
        }

        return userDetailDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUser(UserAddDTO userAddDTO) {
        User user = new User();
        BeanUtil.copyProperties(userAddDTO, user);
        user.setPassword(SecureUtil.md5(userAddDTO.getPassword()));

        // 检测 用户名/手机号码/邮箱 是否重复
        this.checkIsDuplicated(user.getUsername(), null, 0);
        this.checkIsDuplicated(user.getPhoneNumber(), null, 1);
        this.checkIsDuplicated(user.getEmail(), null, 2);

        baseMapper.insert(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(UserUpdateDTO userUpdateDTO) {
        // 根据用户ID获取用户信息
        User user = baseMapper.selectById(userUpdateDTO.getUserId());
        if (user == null) {
            throw new MyException("用户不存在");
        }
        BeanUtil.copyProperties(userUpdateDTO, user);

        // 检测 手机号码/邮箱 是否重复
        this.checkIsDuplicated(user.getPhoneNumber(), user.getUserId(), 1);
        this.checkIsDuplicated(user.getEmail(), user.getUserId(), 2);

        baseMapper.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeUserStatus(UserUpdateStatusDTO userUpdateStatusDTO) {
        // 根据用户ID获取用户信息
        User user = baseMapper.selectById(userUpdateStatusDTO.getUserId());
        if (user == null) {
            throw new MyException("用户不存在");
        }
        BeanUtil.copyProperties(userUpdateStatusDTO, user);

        baseMapper.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetUserPassword(UserUpdatePwdDTO userUpdatePwdDTO) {
        long userId;
        if(userUpdatePwdDTO.getUserId()!=null){
            userId = userUpdatePwdDTO.getUserId();
        }else{
            userId = StpUtil.getLoginIdAsLong();
        }
        // 根据用户ID获取用户信息
        User user = baseMapper.selectById(userId);

        if (user == null) {
            throw new MyException("用户不存在");
        }
        if (userUpdatePwdDTO.getOldPassword() != null && !SecureUtil.md5(userUpdatePwdDTO.getOldPassword()).equals(user.getPassword())) {
            throw new MyException("用户密码错误");
        }
        if (userUpdatePwdDTO.getNewPassword() != null && SecureUtil.md5(userUpdatePwdDTO.getNewPassword()).equals(user.getPassword())) {
            throw new MyException("用户新密码与旧密码相同");
        }

        user.setPassword(SecureUtil.md5(userUpdatePwdDTO.getNewPassword()));
        baseMapper.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUsers(List<Long> userIds) {
        for (Long id : userIds) {
            // 根据用户ID获取用户信息
            User user = baseMapper.selectById(id);
            this.checkCanBeDelete(id, user);
            baseMapper.deleteById(user);
        }
    }

    @Override
    public void checkIsDuplicated(String info, Long userId, int mark) {
        if (StrUtil.isNotBlank(info)) {
            switch (mark) {
                case 0:
                    if (baseMapper.exists(new LambdaQueryWrapper<User>().eq(User::getUsername, info))) {
                        throw new MyException("该用户名已被占用");
                    }
                case 1:
                    if (baseMapper.exists(new LambdaQueryWrapper<User>()
                            .eq(User::getPhoneNumber, info)
                            .ne(userId != null, User::getUserId, userId))) {
                        throw new MyException("该电话号码已使用");
                    }
                case 2:
                    if (baseMapper.exists(new LambdaQueryWrapper<User>()
                            .eq(User::getEmail, info)
                            .ne(userId != null, User::getUserId, userId))) {
                        throw new MyException("该邮件地址已使用");
                    }
                default:
                    break;
            }
        }
    }

    @Override
    public UserDetailDTO getProfile() {
        // 获取当前会话账号id, 并转化为`long`类型
        long loggedInUserId = StpUtil.getLoginIdAsLong();
        // 根据用户ID获取详细信息
        return this.getUserDetail(loggedInUserId);
    }

    /**
     * 检查当前用户是否能被删除
     *
     * @param id
     * @param user
     */
    private void checkCanBeDelete(Long id, User user) {
        // 获取当前会话账号id, 并转化为`long`类型
        long loggedInUserId = StpUtil.getLoginIdAsLong();
        if (id.equals(loggedInUserId)) {
            throw new MyException("当前登录的用户无法删除");
        }
        if (id.equals(1L)) {
            throw new MyException("管理员无法被删除");
        }
        if (user != null && user.getStatus().equals(1)) {
            throw new MyException("已生效的用户无法被删除");
        }
    }
}